home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS03.ADF / C / skewb.c < prev    next >
Text File  |  1986-04-02  |  19KB  |  693 lines

  1. /***************************************************************************
  2. *                                                                          *
  3. *  SKEWB   by Raymond S. Brand                                             *
  4. *                                                                          *
  5. ***************************************************************************/
  6.  
  7. /***************************************************************************
  8. *                                                                          *
  9. *  The weird looking constants are because this program is actually a      *
  10. *  'C' version written for the Amiga of the original Pascal program that   *
  11. *  was written for a Tektronics 4113 Color Raster Display Terminal.        *
  12. *                                                                          *
  13. *                                         RSBX                             *
  14. *                                                                          *
  15. ***************************************************************************/
  16.  
  17. #include <exec/types.h>
  18. #include <intuition/intuition.h>
  19. #include <graphics/gfxmacros.h>
  20.  
  21. #define MAXMODE   1                   /* Highres-Interlace ( 640 x 400 ) */
  22. #define TALLMODE  2                   /* Interlace         ( 320 x 400 ) */
  23. #define WIDEMODE  3                   /* Highres           ( 640 x 200 ) */
  24. #define MINMODE   4                   /*                   ( 320 x 200 ) */
  25.  
  26. #define DEFAULTMODE  MAXMODE
  27.  
  28. #ifndef DISPLAYMODE
  29. #define DISPLAYMODE DEFAULTMODE
  30. #endif
  31.  
  32. #if (DISPLAYMODE == MAXMODE)
  33. #define  DISPLAYWIDTH      640
  34. #define  DISPLAYHEIGHT     400
  35. #define  DISPLAYVIEWMODE   HIRES | LACE
  36. #endif
  37.  
  38. #if (DISPLAYMODE == TALLMODE)
  39. #define  DISPLAYWIDTH      320
  40. #define  DISPLAYHEIGHT     400
  41. #define  DISPLAYVIEWMODE   LACE
  42. #endif
  43.  
  44. #if (DISPLAYMODE == WIDEMODE)
  45. #define  DISPLAYWIDTH      640
  46. #define  DISPLAYHEIGHT     200
  47. #define  DISPLAYVIEWMODE   HIRES
  48. #endif
  49.  
  50. #if (DISPLAYMODE == MINMODE)
  51. #define  DISPLAYWIDTH      320
  52. #define  DISPLAYHEIGHT     200
  53. #define  DISPLAYVIEWMODE   NULL
  54. #endif
  55.  
  56. struct IntuitionBase *IntuitionBase;
  57. struct GfxBase *GfxBase;
  58.  
  59. #define INTUITION_REV 29
  60. #define GRAPHICS_REV  29
  61.  
  62. struct TextAttr MyFont =
  63.   {
  64.    "topaz.font",              /* Font Name        */
  65.    TOPAZ_SIXTY,               /* Font Height      */
  66.    FS_NORMAL,                 /* Style            */
  67.    FPF_ROMFONT,               /* Preferences      */
  68.   };
  69.  
  70. struct NewScreen NewScreen =
  71.   {
  72.    0,                         /* LeftEdge                             */
  73.    0,                         /* TopEdge                              */
  74.    DISPLAYWIDTH,              /* Width                                */
  75.    DISPLAYHEIGHT,             /* Height                               */
  76.    4,                         /* Depth (4 planes = 16 colors)         */
  77.    1,                         /* DetailPen                            */
  78.    2,                         /* BlockPen                             */
  79.    DISPLAYVIEWMODE,           /* ViewModes                            */
  80.    CUSTOMSCREEN,              /* Type                                 */
  81.    &MyFont,                   /* *Font                                */
  82.    "Skewb   by Raymond S. Brand", /* *DefaultTitle                    */
  83.    NULL,                      /* *Gadgets                             */
  84.    NULL,                      /* *CustomBitMap                        */
  85.   };
  86.  
  87. struct Screen *Screen;
  88. struct NewWindow NewWindow;
  89. struct Window *Window1;
  90. struct Window *Window2;
  91.  
  92. struct Verticies
  93.   {
  94.    SHORT X;
  95.    SHORT Y;
  96.   };
  97.  
  98. struct TileRecord
  99.   {
  100.    SHORT Color;
  101.    struct Verticies TileVert[4];
  102.   };
  103.  
  104. struct TileRecord Tiles[6][11][11];
  105.  
  106. WORD  areaverts[25];
  107. struct TmpRas arearas;
  108. struct AreaInfo areadata;
  109.  
  110. VOID  OpenDisplay();
  111. VOID  CloseDisplay();
  112. VOID  SetColors();
  113. SHORT Order();
  114. SHORT Sign();
  115. SHORT CubeCorr_to_ArrayCorr();
  116. SHORT ArrayCorr_to_CubeCorr();
  117. SHORT Tile();
  118. VOID  ChangeDisplay();
  119. VOID  CreateCube();
  120. VOID  RotateSlice();
  121. VOID  MoveSlice();
  122. VOID  ChangeTile();
  123. VOID  InitSkewb();
  124. SHORT Norm_to_Axis();
  125. SHORT Norm_to_Face();
  126. VOID  Swap();
  127. VOID  RotateVector();
  128. VOID  RotatePlane();
  129. VOID  RotateFace();
  130. VOID  RotateSlice();
  131.  
  132. SHORT Cube_Order;
  133.  
  134. #define  Cos1      0.7071067811865
  135. #define  Sin1     -0.7071067811865
  136. #define  Cos2      0.8164965809282
  137. #define  Sin2      0.57735026919
  138. #define  Distance -0.125
  139.  
  140. DOUBLE   M1X =     ( (  700.0 / 4096.0 ) * DISPLAYWIDTH );
  141. DOUBLE   M1Y =     ( (  700.0 / 3048.0 ) * DISPLAYHEIGHT );
  142. DOUBLE   M2X =    -( (  200.0 / 4096.0 ) * DISPLAYWIDTH );
  143. DOUBLE   M2Y =    -( (  200.0 / 3048.0 ) * DISPLAYHEIGHT );
  144.  
  145. SHORT    X1 =      ( ( 1648.0 / 4096.0 ) * DISPLAYWIDTH );
  146. SHORT    Y1 =      ( ( 1606.0 / 3048.0 ) * DISPLAYHEIGHT );
  147. SHORT    Z1 =      1;
  148. SHORT    X2 =      ( (  462.0 / 4096.0 ) * DISPLAYWIDTH );
  149. SHORT    Y2 =      ( ( 2618.0 / 3048.0 ) * DISPLAYHEIGHT );
  150. SHORT    Z2 =     -1;
  151. SHORT    X3 =      ( ( 2836.0 / 4096.0 ) * DISPLAYWIDTH );
  152. SHORT    Y3 =      ( ( 2608.0 / 3048.0 ) * DISPLAYHEIGHT );
  153. SHORT    Z3 =      1;
  154.  
  155. main ()
  156.   {
  157.    struct IntuiMessage *message;
  158.    ULONG class;
  159.    USHORT code;
  160.    SHORT GoodBye;
  161.    SHORT Axis;
  162.    SHORT Plane;
  163.  
  164.    OpenDisplay();
  165.  
  166.    InitSkewb();
  167.  
  168.    GoodBye = FALSE;
  169.    Axis = 1;
  170.    Plane = 0;
  171.  
  172.    FOREVER
  173.      {
  174.       while (message = (struct IntuiMessage *)GetMsg(Window2->UserPort))
  175.         {
  176.          class = message->Class;
  177.          code = message->Code;
  178.          ReplyMsg(message);
  179.  
  180.          if(class == CLOSEWINDOW)
  181.            {
  182.             GoodBye = TRUE;
  183.             break;
  184.            };
  185.          if(class == MOUSEBUTTONS)
  186.            {
  187.             if(code == SELECTDOWN)
  188.               {
  189.                Cube_Order = (Cube_Order - 1) % 9 + 2;
  190.                CreateCube();
  191.                Plane = 0;
  192.                Axis = 1;
  193.               };
  194.            };
  195.         };
  196.       if(GoodBye) break;
  197.  
  198.       Delay(25);
  199.       RotateSlice(Axis,Plane,1);
  200.       Axis += Sign(Axis);
  201.       if(Axis > 3)
  202.          Axis = -1;
  203.       if(Axis < -3)
  204.         {
  205.          Axis = 1;
  206.          Plane = (Plane + 1) % Cube_Order;
  207.         };
  208.      };
  209.  
  210.    CloseDisplay();
  211.  
  212.    exit(TRUE);
  213.   }
  214.  
  215.  
  216.  
  217. VOID  OpenDisplay()
  218.   {
  219.    IntuitionBase = (struct IntuitionBase *)
  220.       OpenLibrary("intuition.library",INTUITION_REV);
  221.    if (IntuitionBase == NULL) exit(20);
  222.  
  223.    GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
  224.    if (GfxBase == NULL) exit(20);
  225.  
  226.    if ((Screen = (struct Screen *)OpenScreen(&NewScreen)) == NULL)
  227.       exit(20);
  228.  
  229.    ShowTitle(Screen,FALSE);  /* Put the Screen title behind any
  230.                                  backdrop window that may exist   */
  231.  
  232.    /* Define Vanilla backdrop window for drawing onto */
  233.    NewWindow.LeftEdge    = 0;
  234.    NewWindow.TopEdge     = 0;
  235.    NewWindow.Width       = DISPLAYWIDTH;
  236.    NewWindow.Height      = DISPLAYHEIGHT;
  237.    NewWindow.DetailPen   = 1;
  238.    NewWindow.BlockPen    = 2;
  239.    NewWindow.IDCMPFlags  = NULL;
  240.    NewWindow.Flags       = SMART_REFRESH | BACKDROP | ACTIVATE;
  241.    NewWindow.FirstGadget = NULL;
  242.    NewWindow.CheckMark   = NULL;
  243.    NewWindow.Title       = NULL;
  244.    NewWindow.Screen      = Screen;
  245.    NewWindow.BitMap      = NULL;
  246.    NewWindow.MinWidth    = DISPLAYWIDTH;
  247.    NewWindow.MinHeight   = DISPLAYHEIGHT;
  248.    NewWindow.MaxWidth    = DISPLAYWIDTH;
  249.    NewWindow.MaxHeight   = DISPLAYHEIGHT;
  250.    NewWindow.Type        = CUSTOMSCREEN;
  251.  
  252.    if ((Window1 = (struct Window *)OpenWindow(&NewWindow)) == NULL)
  253.      {
  254.       CloseScreen(Screen);
  255.       exit(20);
  256.      };
  257.  
  258.    /* Define a window with a close gadget so that we can exit this program */
  259.    NewWindow.LeftEdge    = DISPLAYWIDTH - 100;
  260.    NewWindow.TopEdge     = DISPLAYHEIGHT - 50;
  261.    NewWindow.Width       = 100;
  262.    NewWindow.Height      = 50;
  263.    NewWindow.DetailPen   = 1;
  264.    NewWindow.BlockPen    = 2;
  265.    NewWindow.IDCMPFlags  = CLOSEWINDOW | MOUSEBUTTONS;
  266.    NewWindow.Flags       = SMART_REFRESH | WINDOWDRAG | WINDOWCLOSE;
  267.    NewWindow.FirstGadget = NULL;
  268.    NewWindow.CheckMark   = NULL;
  269.    NewWindow.Title       = "Skewb";
  270.    NewWindow.Screen      = Screen;
  271.    NewWindow.BitMap      = NULL;
  272.    NewWindow.MinWidth    = 100;
  273.    NewWindow.MinHeight   = 50;
  274.    NewWindow.MaxWidth    = 100;
  275.    NewWindow.MaxHeight   = 50;
  276.    NewWindow.Type        = CUSTOMSCREEN;
  277.  
  278.    if ((Window2 = (struct Window *)OpenWindow(&NewWindow)) == NULL)
  279.      {
  280.       CloseWindow(Window1);
  281.       CloseScreen(Screen);
  282.       exit(20);
  283.      };
  284.  
  285.    SetColors();
  286.  
  287.    InitArea(&areadata,areaverts,10);
  288.    Window1->RPort->AreaInfo=&areadata;
  289.  
  290.    if((arearas.RasPtr = (BYTE *)AllocRaster(DISPLAYWIDTH,DISPLAYHEIGHT)) == NULL)
  291.      {
  292.       CloseWindow(Window2);
  293.       CloseWindow(Window1);
  294.       CloseScreen(Screen);
  295.       exit(20);
  296.      };
  297.  
  298.    arearas.Size=RASSIZE(DISPLAYWIDTH,DISPLAYHEIGHT);
  299.    Window1->RPort->TmpRas=&arearas;
  300.  
  301.    SetRast(Window1->RPort,0);
  302.  
  303.    SetOPen(Window1->RPort,15);
  304.   }
  305.  
  306.  
  307.  
  308. VOID  CloseDisplay()
  309.   {
  310.    FreeRaster(arearas.RasPtr,DISPLAYWIDTH,DISPLAYHEIGHT);
  311.  
  312.    CloseWindow(Window1);
  313.    CloseWindow(Window2);
  314.  
  315.    CloseScreen(Screen);
  316.   }
  317.  
  318.  
  319.  
  320. VOID  SetColors()
  321.   {
  322.    SetRGB4(&Screen->ViewPort, 0, 8, 8, 8);      /* background */
  323.    SetRGB4(&Screen->ViewPort, 1,15,15,15);      /* detail     */
  324.    SetRGB4(&Screen->ViewPort, 2, 0, 0, 0);      /* block      */
  325.    SetRGB4(&Screen->ViewPort, 3, 6, 6, 6);
  326.    SetRGB4(&Screen->ViewPort, 4, 6, 6, 6);
  327.    SetRGB4(&Screen->ViewPort, 5, 6, 6, 6);
  328.    SetRGB4(&Screen->ViewPort, 6, 6, 6, 6);
  329.    SetRGB4(&Screen->ViewPort, 7, 6, 6, 6);
  330.    SetRGB4(&Screen->ViewPort, 8,15, 0, 0);      /* red        */
  331.    SetRGB4(&Screen->ViewPort, 9, 0,15, 0);      /* green      */
  332.    SetRGB4(&Screen->ViewPort,10, 0, 0,15);      /* blue       */
  333.    SetRGB4(&Screen->ViewPort,11,15,15,15);      /* white      */
  334.    SetRGB4(&Screen->ViewPort,12,15, 9, 0);      /* orange     */
  335.    SetRGB4(&Screen->ViewPort,13,15,15, 0);      /* yellow     */
  336.    SetRGB4(&Screen->ViewPort,14, 6, 6, 6);
  337.    SetRGB4(&Screen->ViewPort,15, 0, 0, 0);      /* outline    */
  338.   }
  339.  
  340.  
  341.  
  342. SHORT Order()
  343.   {
  344.    return(Cube_Order);
  345.   }
  346.  
  347.  
  348.  
  349. SHORT Sign(number)
  350.    SHORT number;
  351.   {
  352.    if (number == 0) return(0);
  353.    if (number > 0) return(1);
  354.    return(-1);
  355.   }
  356.  
  357.  
  358.  
  359. SHORT CubeCorr_to_ArrayCorr(Cube_Corr)
  360.    SHORT Cube_Corr;
  361.   {
  362.    if ((Cube_Order % 2) == 0) /* even */
  363.  
  364.       return( (SHORT)( Cube_Order / 2 - Cube_Corr
  365.              - ( Cube_Order + 2 - 2 * Cube_Corr ) / ( Cube_Order + 2 ) ) );
  366.  
  367.    else /* odd */
  368.  
  369.       return( (SHORT)( ( Cube_Order - 1 - 2 * Cube_Corr ) / 2 ) );
  370.   }
  371.  
  372.  
  373.  
  374. SHORT ArrayCorr_to_CubeCorr(Array_Corr)
  375.    SHORT Array_Corr;
  376.   {
  377.    if ((Cube_Order % 2) == 0) /* even */
  378.  
  379.       return( (SHORT)( Cube_Order / 2 - Array_Corr
  380.                        - ( 2 * Array_Corr + 2 ) / ( Cube_Order + 1 ) ) );
  381.  
  382.    else /* odd */
  383.  
  384.       return( (SHORT)( ( Cube_Order - 1 - 2 * Array_Corr ) / 2 ) );
  385.   }
  386.  
  387.  
  388.  
  389. SHORT Tile()
  390.   {
  391.   }
  392.  
  393.  
  394.  
  395. VOID  ChangeTile(tileptr,x,y,z)
  396.    struct TileRecord *tileptr;
  397.    SHORT x;
  398.    SHORT y;
  399.    SHORT z;
  400.   {
  401.    SHORT i;
  402.  
  403.    SetAPen(Window1->RPort,tileptr->Color+8);
  404.  
  405.    AreaMove(Window1->RPort,tileptr->TileVert[0].X*z+x,
  406.                            DISPLAYHEIGHT - (tileptr->TileVert[0].Y*z+y));
  407.  
  408.    for (i = 1; i < 4; i++)
  409.       AreaDraw(Window1->RPort,tileptr->TileVert[i].X*z+x,
  410.                               DISPLAYHEIGHT - (tileptr->TileVert[i].Y*z+y));
  411.  
  412.    AreaEnd(Window1->RPort);
  413.   }
  414.  
  415.  
  416.  
  417. VOID  ChangeDisplay(face,x,y)
  418.    SHORT face;
  419.    SHORT x;
  420.    SHORT y;
  421.   {
  422.    struct TileRecord *TileData;
  423.  
  424.    TileData = &Tiles[face][x][y];   /* should point to the tile structure */
  425.  
  426.    if (face < 3)
  427.  
  428.       ChangeTile(TileData,X1,Y1,Z1);
  429.  
  430.    else
  431.  
  432.      {
  433.       ChangeTile(TileData,X2,Y2,Z2);
  434.       ChangeTile(TileData,X3,Y3,Z3);
  435.      };
  436.   }
  437.  
  438.  
  439.  
  440. VOID  CreateCube()
  441.   {
  442.    SHORT Direction;
  443.    SHORT Plane;
  444.    SHORT Index1;
  445.    SHORT Index2;
  446.    SHORT Index3;
  447.    SHORT Index4;
  448.    DOUBLE Temp;
  449.    struct {
  450.            DOUBLE X;
  451.            DOUBLE Y;
  452.           } Matrix[11][11];
  453.    struct TileRecord *withtile;
  454.    DOUBLE Vector[3];
  455.    DOUBLE MultX;
  456.    DOUBLE MultY;
  457.  
  458.    MultX = M1X;
  459.    MultY = M1Y;
  460.    for(Direction=0;Direction<2;Direction++)
  461.      {
  462.       for(Plane=0;Plane<3;Plane++)
  463.         {
  464.          for(Index1=0;Index1<=Cube_Order;Index1++)
  465.            {
  466.             for(Index2=0;Index2<=Cube_Order;Index2++)
  467.               {
  468.                Vector[Plane]=(1.0 - 2.0 * Direction);
  469.                Vector[(Plane+1) % 3]=((Cube_Order - 2.0 * Index1) / Cube_Order);
  470.                Vector[(Plane+2) % 3]=((Cube_Order - 2.0 * Index2) / Cube_Order);
  471.                Temp=(1.0 + Distance * (1.0 - 2.0 * Direction)
  472.                      * ( -Vector[0] * Sin1 * Cos2
  473.                          +Vector[1] * Sin2
  474.                          +Vector[2] * Cos1 * Cos2 ));
  475.                Matrix[Index1][Index2].X=( Vector[0] * Cos1
  476.                                          +Vector[2] * Sin1 ) / Temp;
  477.                Matrix[Index1][Index2].Y=( Vector[0] * Sin1 * Sin2
  478.                                          +Vector[1] * Cos2
  479.                                          -Vector[2] * Cos1 * Sin2 ) / Temp;
  480.               }
  481.            };
  482.          for(Index1=0;Index1<Cube_Order;Index1++)
  483.            {
  484.             for(Index2=0;Index2<Cube_Order;Index2++)
  485.               {
  486.                withtile = &Tiles[Plane + 3 * Direction][Index1][Index2];
  487.                withtile->Color=Plane + 3 * Direction;
  488.  
  489.                for(Index3=0;Index3<2;Index3++)
  490.                  {
  491.                   for(Index4=0;Index4<2;Index4++)
  492.                     {
  493.                      withtile->TileVert[Index3 * 2 + Index4].X
  494.                            = (Matrix[Index1 + Index3]
  495.                                    [Index2 + Index3 + Index4
  496.                                    -2 * Index3 * Index4].X
  497.                                    * (1.0 - 2.0 * Direction) * MultX);
  498.                      withtile->TileVert[Index3 * 2 + Index4].Y
  499.                            = (Matrix[Index1 + Index3]
  500.                                    [Index2 + Index3 + Index4
  501.                                    -2 * Index3 * Index4].Y * MultY);
  502.                     };
  503.                  };
  504.                ChangeDisplay(Plane + 3 * Direction,Index1,Index2);
  505.               };
  506.            };
  507.         };
  508.       MultX = M2X;
  509.       MultY = M2Y;
  510.      };
  511.   }
  512.  
  513.  
  514.  
  515. VOID  InitSkewb()
  516.   {
  517.    Cube_Order = 2;
  518.    CreateCube();
  519.   }
  520.  
  521.  
  522.  
  523. SHORT Norm_to_Axis(Vector)
  524.    SHORT *Vector;
  525.   {
  526.    SHORT Temp;
  527.    SHORT Index;
  528.  
  529.    Temp = 0;
  530.    for(Index=0 ; Index<3 ; Index++)
  531.       Temp += Sign(Vector[Index]) * (Index + 1);
  532.    return(Temp);
  533.   }
  534.  
  535.  
  536.  
  537. SHORT Norm_to_Face(Vector)
  538.    SHORT *Vector;
  539.   {
  540.    SHORT Temp;
  541.  
  542.    Temp = Norm_to_Axis(Vector);
  543.    if(Temp<0)
  544.       Temp = 3 - Temp;
  545.    Temp -= 1;
  546.    return(Temp);
  547.   }
  548.  
  549.  
  550. VOID  Swap_Short(a,b)
  551.    SHORT *a;
  552.    SHORT *b;
  553.   {
  554.    SHORT Temp;
  555.  
  556.    Temp = *a;
  557.    *a = *b;
  558.    *b = Temp;
  559.   }
  560.  
  561.  
  562.  
  563.  
  564. VOID  RotateVector(Vector,Axis,Direction)
  565.    SHORT *Vector;
  566.    SHORT Axis;
  567.    SHORT Direction;
  568.   {
  569.    SHORT Rotate;
  570.  
  571.    Rotate = Sign(Axis) * Sign(Direction);
  572.    Axis = Sign(Axis) * Axis;
  573.    Swap_Short(&Vector[Axis % 3],&Vector[(Axis + 1) % 3]);
  574.  
  575.    if(Rotate>0)
  576.       Vector[(Axis + 1) % 3] *= -1;
  577.    else
  578.       Vector[Axis % 3] *= -1;
  579.   }
  580.  
  581.  
  582.  
  583. VOID  RotatePlane(Axis,Plane,Direction)
  584.    SHORT Axis;
  585.    SHORT Plane;
  586.    SHORT Direction;
  587.   {
  588.    SHORT Norm[3];
  589.    SHORT Tile[3];
  590.    SHORT n;
  591.    SHORT x;
  592.    SHORT y;
  593.    SHORT z;
  594.    SHORT Color;
  595.    SHORT Index1;
  596.    SHORT Index2;
  597.  
  598.    x = Sign(Axis) * Axis - 1;
  599.    y = (x + 1) % 3;
  600.    z = (y + 1) % 3;
  601.    Norm[x] = 0;
  602.    Norm[y] = ArrayCorr_to_CubeCorr(0);
  603.    Norm[z] = 0;
  604.  
  605.    Tile[x] = Sign(Axis) * ArrayCorr_to_CubeCorr(Plane);
  606.  
  607.    for(Index1=0 ; Index1<Cube_Order ; Index1++)
  608.      {
  609.       x = Norm_to_Axis(&Norm);
  610.       x = Sign(x) * x - 1;
  611.       y = (x + 1) % 3;
  612.       z = (y + 1) % 3;
  613.       Tile[x] = Norm[x];
  614.       Tile[y] = ArrayCorr_to_CubeCorr(Index1);
  615.       Color = Tiles[Norm_to_Face(&Norm)]
  616.                    [CubeCorr_to_ArrayCorr(Tile[y])]
  617.                    [CubeCorr_to_ArrayCorr(Tile[z])].Color;
  618.       for(Index2=0 ; Index2<4 ; Index2++)
  619.         {
  620.          RotateVector(&Norm,Axis,Direction);
  621.          RotateVector(&Tile,Axis,Direction);
  622.          x = Norm_to_Axis(&Norm);
  623.          x = Sign(x) * x - 1;
  624.          y = CubeCorr_to_ArrayCorr(Tile[(x + 1) % 3]);
  625.          z = CubeCorr_to_ArrayCorr(Tile[(x + 2) % 3]);
  626.          n = Norm_to_Face(&Norm);
  627.          Swap_Short(&Color,&Tiles[n][y][z].Color);
  628.          ChangeDisplay(n,y,z);
  629.         };
  630.      };
  631.   }
  632.  
  633.  
  634.  
  635. VOID  RotateFace(Axis,Plane,Direction)
  636.    SHORT Axis;
  637.    SHORT Plane;
  638.    SHORT Direction;
  639.   {
  640.    SHORT Tile[3];
  641.    SHORT Color;
  642.    SHORT n;
  643.    SHORT x;
  644.    SHORT y;
  645.    SHORT z;
  646.    SHORT Index1;
  647.    SHORT Index2;
  648.    SHORT Index3;
  649.  
  650.    x = Sign(Axis) * Axis - 1;
  651.    y = (x + 1) % 3;
  652.    z = (y + 1) % 3;
  653.    n = Axis * Sign(ArrayCorr_to_CubeCorr(Plane));
  654.    if(n<0)
  655.       n = 3 - n - 1;
  656.    else
  657.       n -= 1;
  658.    for(Index1=0 ; Index1 < (Cube_Order / 2) ; Index1++)
  659.      {
  660.       for(Index2=0 ; Index2 <= (Cube_Order - 2 * (Index1 + 1)) ; Index2++)
  661.         {
  662.          Tile[y] = ArrayCorr_to_CubeCorr(Index1);
  663.          Tile[z] = ArrayCorr_to_CubeCorr(Index1 + Index2);
  664.          Color = Tiles[n][Index1][Index1 + Index2].Color;
  665.          for(Index3=0 ; Index3<4 ; Index3++)
  666.            {
  667.             RotateVector(&Tile,Axis,Direction);
  668.             Swap_Short(&Color,&Tiles[n]
  669.                                     [CubeCorr_to_ArrayCorr(Tile[y])]
  670.                                     [CubeCorr_to_ArrayCorr(Tile[z])].Color);
  671.             ChangeDisplay(n,CubeCorr_to_ArrayCorr(Tile[y])
  672.                            ,CubeCorr_to_ArrayCorr(Tile[z]));
  673.            };
  674.         };
  675.      };
  676.   }
  677.  
  678.  
  679. VOID  RotateSlice(Axis,Plane,Displacement)
  680.    SHORT Axis;
  681.    SHORT Plane;
  682.    SHORT Displacement;
  683.   {
  684.    for( ; Displacement != 0 ; Displacement -= Sign(Displacement))
  685.      {
  686.       RotatePlane(Axis,Plane,Displacement);
  687.       if( (Plane * (Cube_Order - Plane - 1)) == 0 )
  688.          RotateFace(Axis,Plane,Displacement);
  689.      };
  690.   }
  691.  
  692. 
  693.